package com.heaven.customerServer.customerController;

import com.heaven.customerServer.customerController.vo.uploadFile.*;
import com.heaven.service.minio.BigFileUploadService;
import com.heaven.utils.R;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.MediaType;
import org.springframework.http.codec.multipart.FilePart;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Mono;

@RestController
@Slf4j
@RequestMapping("heaven-server/upload")
public class UploadFileController {
    @Autowired
    private BigFileUploadService bigFileUploadService;

    @GetMapping("/auth/start")
    public R getUploadStartIndex(@RequestParam("md5") String md5, @RequestParam("maxBlobSize") Long maxBlobSize,
                                 @RequestParam("size") Long size,@RequestParam("fileName") String fileName) {
        BlobStartRes ans = bigFileUploadService.getStartBlobIndex(md5, maxBlobSize, size, fileName);
        return R.okData(ans);
    }

    /**
     * 大文件分块上传专用接口（webflux）
     * 客户端->服务端->minio，分块首先由服务端传递给minio持久化保存，
     * 分块传递完成后服务端从minio下载分块合并到服务器本地后在上传完整文件给minio，适用于分布式环境
     * @param feature 文件特征
     * @return 返回文件上传结果
     */
    @PostMapping(value = "/auth/blob", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public Mono<R> uploadBlob(@Valid BigFileFeatureReq feature) {
        FilePart blob = feature.getBlob();
        return DataBufferUtils.join(blob.content()).map(DataBuffer::asInputStream).map(inputStream -> {
            UploadBigFileRes ans = bigFileUploadService.uploadBigFileBlob(inputStream, feature.getContentLength(), feature);
            if (ans.getStatus() == 1) {
                bigFileUploadService.mergeBlobs(feature.getMd5(), feature.getMaxBlobSize(), feature.getSize(), feature.getFileName());
            }
            return R.okData(ans);
        });
    }

    /**
     * 本地缓存大文件分块上传专用接口（webflux）
     * 客户端将分块传递给服务端，服务端现在本地缓存这些分块，客户端上传完成后合并到服务器本地再把完整的文件上传给minio，适用于单机环境
     * @param feature 文件特征
     * @return 返回文件上传结果
     */
    @PostMapping(value = "/auth/blob/local-cache", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public Mono<R> uploadBlobLocalCache(@Valid BigFileFeatureReq feature) {
        FilePart blob = feature.getBlob();
        return DataBufferUtils.join(blob.content()).map(DataBuffer::asInputStream).map(inputStream -> {
            UploadBigFileRes ans = bigFileUploadService.uploadFileBlobLocalCache(inputStream, feature);
            if (ans.getStatus() == 1) {
                bigFileUploadService.mergeBlobsLocalCache(feature.getMd5(), feature.getMaxBlobSize(), feature.getSize(), feature.getFileName());
            }
            return R.okData(ans);
        });
    }

    /**
     * 单文件直传（小于50MB）
     * @param feature 文件特征
     * @return 返回文件上传结果
     */
    @PostMapping(value = "/auth/single-whole", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public Mono<R> uploadSingleWhole(@Valid FileFeatureReq feature) {
        FilePart file = feature.getFile();
        return DataBufferUtils.join(file.content()).map(DataBuffer::asInputStream).map(inputStream -> {
            UploadFileRes ans = bigFileUploadService.uploadSingleWhole(feature, inputStream);
            return R.okData(ans);
        });
    }
}
